package com.nasarius.bank.scorecard.web.controller.user;

import java.io.IOException;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomCollectionEditor;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.nasarius.bank.scorecard.dao.BankDetailsDAO;
import com.nasarius.bank.scorecard.dao.BankFactorsActualDAO;
import com.nasarius.bank.scorecard.domain.BankFactorsActual;
import com.nasarius.bank.vo.BankFactorListVO;
import com.nasarius.bank.vo.BankFactorVO;
import com.nasarius.bank.vo.FactorPeriodVO;
import com.nasarius.bank.vo.PeriodVO;
import com.nasarius.bank.vo.SearchVO;

@Controller
public class FactorAnalysisController {
	/** Logger that is available to subclasses */
	protected final Log LOG = LogFactory.getLog(getClass());	
	@Autowired
	private BankDetailsDAO bankDetailsDAO;
	@Autowired 
	private BankFactorsActualDAO bankFactorsActualDAO;
	public BankDetailsDAO getBankDetailsDAO() {
		return bankDetailsDAO;
	}

	public BankFactorsActualDAO getBankFactorsActualDAO() {
		return bankFactorsActualDAO;
	}

	@InitBinder
	protected void initBinder(ServletRequestDataBinder binder) {
		binder.registerCustomEditor(List.class, new CustomCollectionEditor(
				List.class));
		binder.registerCustomEditor(Date.class, new CustomDateEditor(
				new SimpleDateFormat("dd/MM/yyyy"), true));
	}

	@RequestMapping(value = "/factorAnalysis/form", method = RequestMethod.GET)
	public SearchVO newRequest(@RequestParam(required = false) String searchId,
			Model model) {
		SearchVO searchVO = new SearchVO();
		return searchVO;
	}
	@RequestMapping(value = "/factorAnalysis/graphdummy", method = RequestMethod.GET)
	public void graphdummy(SearchVO searchVO, Model model, HttpServletRequest r){
		HttpSession session = r.getSession();
		session.setAttribute("searchVO", searchVO);
	}
	@RequestMapping(value = "/factorAnalysis/graph", method = RequestMethod.GET)
	public void graph(HttpServletRequest r, HttpServletResponse rs, Model model) throws JAXBException, IOException{
		HttpSession session = r.getSession();
		SearchVO searchVO = (SearchVO)session.getAttribute("searchVO");
		BankFactorListVO bankFactorListVO = formGraphOutput(searchVO);
		// create JAXB context and instantiate marshaller
		JAXBContext context = JAXBContext.newInstance(BankFactorListVO.class);
		Marshaller m = context.createMarshaller();
		StringWriter sr= new StringWriter();
		m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 
		m.marshal(bankFactorListVO, sr);	
		rs.setContentType("text/html;charset=UTF-8");
	    rs.getWriter().append(sr.toString());
		session.removeAttribute("searchVO");
		model.addAttribute("scorecardGraph",sr.toString().replaceAll("\"", "'"));
				//r.getQueryString().replaceAll("&", ";")+";out=xml");
	}

	private BankFactorListVO formGraphOutput(SearchVO searchVO) {
		List<BankFactorsActual> bankFactorActualList =	bankFactorsActualDAO.factorsForFactorAnalysis(searchVO.getFromDt(), searchVO.getToDt());
		BankFactorListVO bankFactorListVO = new BankFactorListVO();
		SimpleDateFormat s = new SimpleDateFormat("dd/MM/yyyy");
		String previousBankCode = "";
		String previousFactor = "";
		BankFactorVO bankFactorVO = new BankFactorVO();
		FactorPeriodVO factorPeriodVO = new FactorPeriodVO();		
		List<BankFactorVO> bankFactorList = new ArrayList<BankFactorVO>();
		List<FactorPeriodVO> factorPeriodList = new ArrayList<FactorPeriodVO>();
		List<PeriodVO> periodListVO = new ArrayList<PeriodVO>();		
		for(BankFactorsActual bankFactorsActual : bankFactorActualList){
			String bankCode = bankFactorsActual.getBankcode();
			String factorID = bankFactorsActual.getFactorid().toString();
			if(!previousBankCode.equals(bankCode)){
				previousBankCode = bankCode;
				if(factorPeriodList.size() > 0){
					bankFactorVO.setFactorPeriodList(factorPeriodList);
					bankFactorList.add(bankFactorVO);
					factorPeriodList = new ArrayList<FactorPeriodVO>();
				}
				bankFactorVO = new BankFactorVO();
				bankFactorVO.setBankName(bankCode);
			}
			if(!previousFactor.equals(factorID)){
				previousFactor = factorID;
				if(periodListVO.size() > 0){
					factorPeriodVO.setPeriodListVO(periodListVO);
					factorPeriodList.add(factorPeriodVO);
					periodListVO = new ArrayList<PeriodVO>();
				}
				factorPeriodVO = new FactorPeriodVO();
				factorPeriodVO.setFactorID(factorID);
				factorPeriodVO.setFactorName(bankFactorsActual.getFactorName());
			}
			formPeriodListVO(s, periodListVO, bankFactorsActual);
		}
		if(factorPeriodList.size() > 0){
			bankFactorVO.setFactorPeriodList(factorPeriodList);
			bankFactorList.add(bankFactorVO);
		}
		bankFactorListVO.setBankFactorVOList(bankFactorList);
		return bankFactorListVO;
	}

	private void formPeriodListVO(SimpleDateFormat s,
			List<PeriodVO> periodListVO, BankFactorsActual bankFactorsActual) {
		PeriodVO periodVO = new PeriodVO();
		String period = s.format(bankFactorsActual.getFromdt()) + " - "
		+ s.format(bankFactorsActual.getTodt());
		periodVO.setPeriod(period);
		periodVO.setExpectedValue(bankFactorsActual.getExpectedValue());
		periodVO.setActualvalue(bankFactorsActual.getActualvalue());
		periodVO.setUnits(bankFactorsActual.getUnits());
		periodListVO.add(periodVO);
	}
}
